// yfs client.  implements FS operations using extent and lock server
#include "yfs_client.h"
#include "extent_client.h"
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


yfs_client::yfs_client(std::string extent_dst, std::string lock_dst)
{
  ec = new extent_client(extent_dst);

}

yfs_client::inum
yfs_client::n2i(std::string n)
{
  std::istringstream ist(n);
  unsigned long long finum;
  ist >> finum;
  return finum;
}

std::string
yfs_client::filename(inum inum)
{
  std::ostringstream ost;
  ost << inum;
  return ost.str();
}

bool
yfs_client::isfile(inum inum)
{
  if(inum & 0x80000000)
    return true;
  return false;
}

bool
yfs_client::isdir(inum inum)
{
  return ! isfile(inum);
}

int
yfs_client::put(inum inum, std::string st)
{
	if(ec->put(inum, st) == extent_protocol::OK)
	{
		return OK;
	}
	return NOENT;
}

int
yfs_client::get(inum inum, std::string& st)
{
	if(ec->get(inum, st) == extent_protocol::OK)
	{
		return OK;
	}
	return NOENT;
}

int
yfs_client::remove(inum inum)
{
    if(ec->remove(inum) == extent_protocol::OK)
    {
         return OK;
    }
    return NOENT;
}

int
yfs_client::getattr(inum inum, extent_protocol::attr &at)
{
	if(ec->getattr(inum, at) == extent_protocol::OK)
	{
		return OK;
	}
	return NOENT;
}

int
yfs_client::getfile(inum inum, fileinfo &fin)
{
  int r = OK;


  printf("getfile %016llx\n", inum);
  extent_protocol::attr a;
  if (ec->getattr(inum, a) != extent_protocol::OK) {
    r = IOERR;
    goto release;
  }

  fin.atime = a.atime;
  fin.mtime = a.mtime;
  fin.ctime = a.ctime;
  fin.size = a.size;
  printf("getfile %016llx -> sz %llu\n", inum, fin.size);

 release:

  return r;
}

int
yfs_client::getdir(inum inum, dirinfo &din)
{
  int r = OK;


  printf("getdir %016llx\n", inum);
  extent_protocol::attr a;
  if (ec->getattr(inum, a) != extent_protocol::OK) {
    r = IOERR;
    goto release;
  }
  din.atime = a.atime;
  din.mtime = a.mtime;
  din.ctime = a.ctime;

 release:
  return r;
}

//called by createhelper in fuse.cc
int
yfs_client::createfile(inum parent, inum ino, const char* name, fileinfo &fin)
{
  int r = OK;
  std::string directory;
  extent_protocol::attr a;

  //acquire locks
  lc->acquire(parent);
  lc->acquire(ino);

  //make sure ino is correct
  if (!isfile(ino)){
    r = IOERR;
    goto release;
  }

  //check if file already exists
  ec->get(parent, directory);
  if ( directory.find(std::string(name)+"\t") != std::string::npos) {
    return IOERR;
  }

  //add file to parent directory
  directory += name;
  directory += "\t";
  directory += filename(ino);
  directory += " ";
  ec->put(parent, directory);

  //add new file to extent
  ec->put(ino, "");

  //get file info
  if (ec->getattr(ino, a) != extent_protocol::OK) {
    r = IOERR;
    goto release;
  }
  fin.atime = a.atime;
  fin.mtime = a.mtime;
  fin.ctime = a.ctime;
  fin.size = a.size;

 release:
  lc->release(ino);
  lc->release(parent);
  return r;
}
